package com.hu.biz.signature;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.alibaba.fastjson.JSON;
import com.hu.biz.encrypt.Encrypt;
import com.hu.biz.encrypt.EncryptProcessor;
import com.hu.biz.filter.CustomHttpServletRequest;
import com.hu.common.util.adm.ServletUtil;
import com.hu.common.util.adm.SpringKit;
import lombok.extern.slf4j.Slf4j;


import javax.servlet.http.HttpServletRequest;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author 00351634
 * @version 1.0
 * @date 2024/10/15 8:11
 * @description: SHA256WithRSA签名处理类
 */
@Slf4j
public class SHA256WithRSASignatureHandler extends AbstractSignatureHandler {

    private final String HEADER_SIGNATURE = "sign";
    private final String HEADER_APPID = "appId";
    private final String HEADER_TIMESTAMP = "timestamp";
    private final String HEADER_REQID = "reqId";

    public SHA256WithRSASignatureHandler(String key) {
        super(key);
    }

    @Override
    public String calcSignature() {
        CustomHttpServletRequest request = (CustomHttpServletRequest) ServletUtil.getRequest();
        String appId = request.getHeader(HEADER_APPID);
        String timestamp = request.getHeader(HEADER_TIMESTAMP);
        String reqId = request.getHeader(HEADER_REQID);
        if (StrUtil.hasBlank(appId, timestamp, reqId)) {
            throw new IllegalArgumentException("请求头中缺少必要的参数");
        }
        SignatureProperties properties = SpringKit.getBean(SignatureProperties.class);
        if (System.currentTimeMillis() - Convert.toLong(timestamp) > properties.getValidTime() * 1000) {
            throw new IllegalArgumentException("请求参数超时");
        }
        properties.getPlatform().stream().filter(p -> p.getAppId().equals(appId)).findFirst().orElseThrow(() -> new IllegalArgumentException(appId + "未在本平台注册，请检查配置！"));
        String bodyString = request.getBodyString();
        Map<String, String> map = new LinkedHashMap<>();
        map.put(HEADER_APPID, appId);
        map.put(HEADER_TIMESTAMP, timestamp);
        map.put(HEADER_REQID, reqId);
        map.put("body", bodyString);
        log.info("计算签名原文:{}", JSON.toJSONString(map));
        String signaturePlainStr = map.entrySet().stream().map(entry -> entry.getKey() + "=" + entry.getValue())
                .reduce((a, b) -> a + "&" + b).orElseThrow(() -> new IllegalArgumentException("计算签名原文失败"));
        return DigestUtil.sha256Hex(signaturePlainStr);
    }

    @Override
    public String encryptSignature() {
        EncryptProcessor encryptProcessor = this.getEncryptProcessor();
        return Base64.encode(encryptProcessor.encode(new Encrypt(calcSignature())));
    }

    @Override
    public String getClientSignature() {
        HttpServletRequest request = ServletUtil.getRequest();
        String clientSignature = request.getHeader(HEADER_SIGNATURE);
        if (StrUtil.isBlank(clientSignature)) {
            throw new IllegalArgumentException("请求头中缺少签名");
        }
        return this.getEncryptProcessor().decode(Base64.decodeStr(clientSignature)).getValue();
    }
}
